use std::cell::RefCell;

use lrlex::lrlex_mod;
use lrpar::lrpar_mod;
use markdown_elements::{Listener, ListenerDelegate, TListener};

// Using `lrlex_mod!` brings the lexer for `calc.l` into scope. By default the
// module name will be `calc_l` (i.e. the file name, minus any extensions,
// with a suffix of `_l`).
lrlex_mod!("markdown.l");
// Using `lrpar_mod!` brings the parser for `calc.y` into scope. By default the
// module name will be `calc_y` (i.e. the file name, minus any extensions,
// with a suffix of `_y`).
lrpar_mod!("markdown.y");
struct A();
impl Listener for A {
    fn when(&mut self, _item: &markdown_elements::Markdown) {
        // println!("{}",item);
    }
}
pub fn parse(input: &str) -> (Option<Vec<markdown_elements::Markdown>>, Option<String>) {
    let mut listener = A();
    let listener: TListener = RefCell::new(ListenerDelegate::new(&mut listener));
    parse_with_listener(input, &listener)
}
pub fn parse_with_listener<'a>(
    input: &'a str,
    listener: &'_ TListener,
) -> (Option<Vec<markdown_elements::Markdown<'a>>>, Option<String>) {
    let lexerdef = markdown_l::lexerdef();
    let lexer = lexerdef.lexer(input);

    let (res, errs) = markdown_y::parse(&lexer, listener);
    let err_info = errs
        .iter()
        .map(|f| f.pp(&lexer, &markdown_y::token_epp))
        .map(|e| {
            let e: Vec<&str> = e.lines().take(4).collect();
            e.join("\n")
        })
        .reduce(|acc, e| format!("{acc}\n{e}"));
    (res, err_info)
}

#[cfg(test)]
mod test {}
